﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using Microsoft.Win32;

namespace BZ.Common
{
    /// <summary>
    /// 通用杂项功能处理
    /// </summary>
    public class CommonUtility
    {
        #region 数组列表处理

        /// <summary>
        /// 数组初始化
        /// </summary>
        /// <typeparam name="T">数组类型</typeparam>
        /// <param name="_array">数组</param>
        /// <param name="_initValue">初始化值</param>
        public static void InitArray<T>(T[] _array, T _initValue)
        {
            if (_array != null && _array.Length > 0)
            {
                for (int i = 0; i < _array.Length; i++)
                {
                    _array[i] = _initValue;
                }
            }
        }



        /// <summary>
        /// 替换list中指定的数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="_source">列表</param>
        /// <param name="_newItem">新模型</param>
        /// <param name="_func">替换条件</param>
        /// <param name="_result">替换是否成功</param>
        /// <returns>替换后的列表</returns>
        public static List<T> ListItemReplace<T>(List<T> _source, T _newItem, Predicate<T> _func, out bool _result)
        {
            _result = false;
            if (_source != null && _source.Count > 0)
            {
                int myIndex = -1;
                myIndex = _source.FindIndex(_func);
                if (myIndex >= 0)
                {
                    _result = true;
                    _source[myIndex] = _newItem;
                }
            }
            return _source;
        }

        #endregion

        #region 日期时间处理


        /// <summary>
        /// 日期转年月日
        /// </summary>
        /// <param name="_dateTime"></param>
        /// <returns></returns>
        public static string DateToChnDate(DateTime _dateTime)
        {
            StringBuilder Result = new StringBuilder();
            if (_dateTime != null)
            {
                Result.Append(NumberToShuzi(_dateTime.Year.ToString()));
                Result.Append("年");

                string myTemp = string.Empty;
                myTemp = _dateTime.Month.ToString();
                if (_dateTime.Month > 9)
                {
                    myTemp = "十" + _dateTime.Month.ToString()[1];
                    myTemp = myTemp.TrimEnd('0');
                }
                Result.Append(NumberToShuzi(myTemp));
                Result.Append("月");

                myTemp = _dateTime.Day.ToString();
                if (_dateTime.Day > 9)
                {
                    string myTenPos = string.Empty;
                    if (_dateTime.Day > 19)
                    {
                        myTenPos = _dateTime.Day.ToString()[0].ToString();
                    }
                    myTemp = myTenPos + "十" + _dateTime.Day.ToString()[1];
                    myTemp = myTemp.TrimEnd('0');
                }
                Result.Append(NumberToShuzi(myTemp));
                Result.Append("日");

            }
            return Result.ToString();
        }

        /// <summary>
        /// 数字转换为中文类型的字符串
        /// </summary>
        /// <param name="_number"></param>
        /// <returns></returns>
        public static string NumberToShuzi(string _number)
        {
            string result = string.Empty;
            if (!string.IsNullOrEmpty(_number))
            {
                result = new string(NumberToShuzi(_number.ToCharArray()));
            }
            return result;
        }

        /// <summary>
        /// 数字转换为中文类型的字符
        /// </summary>
        /// <param name="_number"></param>
        /// <returns></returns>
        public static char[] NumberToShuzi(params char[] _number)
        {
            for (int i = 0; i < _number.Count(); i++)
            {
                _number[i] = NumberToShuzi(_number[i]);
            }
            return _number;
        }

        /// <summary>
        /// 数字转换为中文类型的字符
        /// </summary>
        /// <param name="_number"></param>
        /// <returns></returns>
        public static char NumberToShuzi(char _number)
        {
            switch (_number)
            {
                case '0':
                    _number = '〇';
                    break;
                case '1':
                    _number = '一';
                    break;
                case '2':
                    _number = '二';
                    break;
                case '3':
                    _number = '三';
                    break;
                case '4':
                    _number = '四';
                    break;
                case '5':
                    _number = '五';
                    break;
                case '6':
                    _number = '六';
                    break;
                case '7':
                    _number = '七';
                    break;
                case '8':
                    _number = '八';
                    break;
                case '9':
                    _number = '九';
                    break;
                default:
                    break;
            }
            return _number;
        }

        /// <summary>
        /// 格式化时间字符串,以默认格式，若转换错误以"——"输出
        /// </summary>
        /// <param name="_dateTime">时间</param>
        /// <param name="_isShort">是否短版</param>
        /// <returns></returns>
        public static string FormatDateTime(object _dateTime, bool _isShort = false)
        {
            string myResult = string.Empty;
            try
            {
                DateTime myDate = Convert.ToDateTime(_dateTime);
                if (!_isShort)
                {
                    myResult = myDate == default(DateTime) ? "——" : myDate.ToString("yyyy-MM-dd HH:mm:ss");
                }
                else
                {
                    myResult = myDate == default(DateTime) ? "——" : myDate.ToString("yyyy-MM-dd");
                }
            }
            catch
            {
                myResult = "——";
            }
            return myResult;
        }


        /// <summary>
        /// 获取指定日期所在的季度,及季度区间日期
        /// </summary>
        /// <param name="_dateTime">日期</param>
        /// <param name="_startQuarterDateTime">out 日期所在季度起始日期</param>
        /// <param name="_endQuarterDatetime">out 日期所在季度结尾日期</param>
        /// <returns>季度数</returns>
        public static int GetDateQuarter(DateTime _dateTime, out DateTime _startQuarterDateTime, out DateTime _endQuarterDatetime)
        {
            int myQuarter = 0;
            _startQuarterDateTime = DateTime.MinValue;
            _endQuarterDatetime = DateTime.MaxValue;
            if (_dateTime > DateTime.MinValue && _dateTime < DateTime.MaxValue)
            {
                myQuarter = ((_dateTime.Month - 1) / 3) + 1;
                _startQuarterDateTime = _dateTime.AddDays(1 - _dateTime.Day).AddMonths(0 - (_dateTime.Month - 1) % 3);
                _endQuarterDatetime = _startQuarterDateTime.AddMonths(3).AddDays(-1);
            }
            return myQuarter;
        }

        /// <summary>
        /// 将字符串类型的日期转换为合法的datetime
        /// </summary>
        /// <param name="dateStr">格式: yyyy-MM-dd HH:mm:ss</param>
        /// <returns>如果字符串为null 或者 处理出现错误则返回  DateTime.MinValue</returns>
        public static DateTime GetDate(string dateStr)
        {
            DateTime curDate = DateTime.MinValue;
            if (!string.IsNullOrEmpty(dateStr))
            {
                try
                {
                    curDate = Convert.ToDateTime(dateStr);
                }
                catch
                {
                    string[] dateNums = Regex.Split(dateStr, @"[^\d]+");
                    if (dateNums != null && dateNums.Length == 6)
                    {
                        try
                        {
                            curDate = DateTime.MinValue;
                            curDate = curDate.AddYears(Convert.ToInt32(dateNums[0]) - 1);
                            curDate = curDate.AddMonths(Convert.ToInt32(dateNums[1]) - 1);
                            curDate = curDate.AddDays(Convert.ToInt32(dateNums[2]) - 1);
                            curDate = curDate.AddHours(Convert.ToInt32(dateNums[3]));
                            curDate = curDate.AddMinutes(Convert.ToInt32(dateNums[4]));
                            curDate = curDate.AddSeconds(Convert.ToInt32(dateNums[5]));
                        }
                        catch { curDate = DateTime.MinValue; }
                    }
                }
            }
            return curDate;
        }
        
        #endregion

        #region 获取GUID

        /// <summary>
        /// 获取Guid
        /// </summary>
        /// <returns></returns>
        public static string GetGuid()
        {
            return Guid.NewGuid().ToString("N");
        }

        #endregion

        #region "MD5加密"
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="_source">加密字符</param>
        /// <param name="_Is16bit">加密位数为16还是32位</param>
        /// <returns></returns>
        public static string GetMD5Str(string _source, bool _Is16bit)
        {
            string strEncrypt = string.Empty;
            if (_Is16bit)
            {
                strEncrypt = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(_source, "md5").Substring(8, 16);
            }
            else
            {
                strEncrypt = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(_source, "md5");
            }

            return strEncrypt.ToLower();
        }
        #endregion

        #region "获取用户IP地址"
        /// <summary>
        /// 获取用户IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetIPAddress()
        {
            return System.Web.HttpContext.Current.Request.UserHostAddress;
        }
        #endregion

        #region "3des加解密字符串"

        /// <summary>
        /// 3des加密函数(ECB加密模式,PaddingMode.PKCS7,无IV)
        /// </summary>
        /// <param name="_source">加密字符</param>
        /// <param name="_key">加密key(24字符)</param>
        /// <returns>加密后Base64字符</returns>
        public static string EncryptString(string _source, string _key)
        {
            string enstring = "加密出错!";
            ICryptoTransform ct; //需要此接口才能在任何服务提供程序上调用 CreateEncryptor 方法，服务提供程序将返回定义该接口的实际 encryptor 对象。
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;
            SymmetricAlgorithm des3 = SymmetricAlgorithm.Create("TripleDES");
            des3.Mode = CipherMode.ECB;
            des3.Key = Encoding.UTF8.GetBytes(StringUtility.splitStringLen(_key, 24, '0'));
            //des3.KeySize = 192;
            des3.Padding = PaddingMode.PKCS7;

            ct = des3.CreateEncryptor();

            byt = Encoding.UTF8.GetBytes(_source);//将原始字符串转换成字节数组。大多数 .NET 加密算法处理的是字节数组而不是字符串。

            //创建 CryptoStream 对象 cs 后，现在使用 CryptoStream 对象的 Write 方法将数据写入到内存数据流。这就是进行实际加密的方法，加密每个数据块时，数据将被写入 MemoryStream 对象。

            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            try
            {
                cs.Write(byt, 0, byt.Length);
                cs.FlushFinalBlock();
                enstring = Convert.ToBase64String(ms.ToArray());
            }
            catch (Exception ex)
            {
                enstring = ex.ToString();
            }
            finally
            {
                cs.Close();
                cs.Dispose();
                ms.Close();
                ms.Dispose();
                des3.Clear();
                ct.Dispose();
            }
            enstring = Convert.ToBase64String(ms.ToArray());
            //return enstring.Replace('+', '_');
            return enstring;
        }

        /// <summary>
        /// 3des解密函数(ECB加密模式,PaddingMode.PKCS7,无IV)
        /// </summary>
        /// <param name="_source">解密字符</param>
        /// <param name="_key">解密key(24字符)</param>
        /// <returns>解密后字符</returns>
        public static string DecryptString(string _source, string _key)
        {
            string destring = "解密字符失败!";
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            SymmetricAlgorithm des3 = SymmetricAlgorithm.Create("TripleDES");
            des3.Mode = CipherMode.ECB;
            des3.Key = Encoding.UTF8.GetBytes(StringUtility.splitStringLen(_key, 24, '0'));
            //des3.KeySize = 192;
            des3.Padding = PaddingMode.PKCS7;

            ct = des3.CreateDecryptor();

            //byt = Convert.FromBase64String(decryptString.Replace('_', '+'));
            byt = Convert.FromBase64String(_source);

            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            try
            {
                cs.Write(byt, 0, byt.Length);
                cs.FlushFinalBlock();
                destring = Encoding.UTF8.GetString(ms.ToArray());
            }
            catch (Exception ex)
            {
                destring = ex.ToString();
            }
            finally
            {
                ms.Close();
                cs.Close();
                ms.Dispose();
                cs.Dispose();
                ct.Dispose();
                des3.Clear();
            }
            return destring;
        }
        #endregion

        #region Html 格式化处理

        /// <summary>
        /// 用键值模型来返回样式字符串，主要用来处理高度控制
        /// </summary>
        /// <param name="_styles"></param>
        /// <returns></returns>
        public static string GetStylePart(params KeyValuePair<string, string>[] _styles)
        {
            StringBuilder myResult = new StringBuilder(20);
            if (_styles != null && _styles.Count() > 0)
            {
                myResult.Append("style=\"");
                foreach (KeyValuePair<string, string> myValue in _styles)
                {
                    myResult.Append(myValue.Key);
                    myResult.Append(":");
                    myResult.Append(myValue.Value);
                }
                myResult.Append("\"");
            }
            return myResult.ToString();
        }



        #endregion

        #region 去除HTML
        /// <summary>
        /// 返回不含html标签的，前提是 <body> 部分的内容
        /// </summary>
        /// <param name="_source"></param>
        /// <returns></returns>
        public static string NoHTML(string _source)  //替换HTML标记
        {
            if (!string.IsNullOrEmpty(_source))
            {
                //删除脚本
                _source = Regex.Replace(_source, @"<script[^>]*>[(^<)\s\S]*?</script>", "", RegexOptions.IgnoreCase);
                //删除HTML
                _source = Regex.Replace(_source, @"&#(.[^>]*);", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"([rn])[s]+", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"-->", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"<!--.*", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(quot|#34);", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(iexcl|#161);", "xa1", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(cent|#162);", "xa2", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(pound|#163);", "xa3", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&(copy|#169);", "xa9", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"&#(d+);", "", RegexOptions.IgnoreCase);
                _source = Regex.Replace(_source, @"<img[^>]*>;", "", RegexOptions.IgnoreCase);

                //下面这些没啥用好像
                //_source.Replace("<", "");
                //_source.Replace(">", "");
                //_source.Replace("rn", "");
                //_source = HttpUtility.HtmlEncode(_source).Trim();
            }
            return _source;
        }
        #endregion 

        #region WinService 功能

        /// <summary>
        /// 获取服务所在安装路径(依赖注册表)
        /// </summary>
        /// <param name="ServiceName">服务名</param>
        /// <returns>服务安装路径 如：c:\path\serverpath</returns>
        public static string GetWindowsServiceInstallPath(string ServiceName)
        {
            string key = @"SYSTEM\CurrentControlSet\Services\" + ServiceName;
            string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
            path = path.Replace("\"", string.Empty);//替换掉双引号
            FileInfo fi = new FileInfo(path);
            return fi.Directory.ToString();
        }

        #endregion

    }
}
